#include "String11.h"

namespace lmr
{
    const size_t string::npos = -1;

    void string::reserve(size_t n)
    {
        cout << "reserve:" << n << endl;
        if(n > _capacity)
        {
            char* tmp = new char[n + 1];
            strcpy(tmp, _str);
            delete[] _str;
            _str = tmp;
            _capacity = n;
        }
        //n <= _capacity 容量不变
    }

    void string::push_back(char ch)
    {
        if(_size == _capacity)
        {
            reserve(_capacity == 0 ? 4 : _capacity * 2);
        }
        _str[_size] = ch;
        _size++;
        _str[_size] = '\0';
    }

    void string::append(const char* str)
    {
        size_t len = strlen(str);
        if(len + _size > _capacity)
        {
            // 大于2倍，需要多少开多少，小于2倍按2倍扩
            reserve(len + _size > _capacity * 2 ? len + _size : _capacity * 2);
        }
        strcpy(_str + _size, str);
        _size = len;
    }

    string& string::operator+=(char ch)
    {
        push_back(ch);
        return *this;
    }
    string& string::operator+=(const char* str)
    {
        append(str);
        return *this;
    }
    string& string::operator+=(const string& str) 
    {
        return *this += str.c_str();
    }

    void string::insert(size_t pos, char ch)
    {
        assert(pos <= _size);
        if(_size == _capacity)
        {
            reserve(_capacity == 0 ? 4 : _capacity * 2);
        }
        size_t end =  _size + 1;
        while(end > pos)
        {
            _str[end] = _str[end - 1];
            end--;
        }
        _str[pos] = ch;
        _size++;
    }

    void string::insert(size_t pos, const char* str)
    {
        assert(pos <= _size);
        size_t len = strlen(str);
        if(len + _size > _capacity)
        {
            reserve(len + _size > 2 * _capacity ? len + _size : _capacity * 2);
        }
        size_t end = _size + len;
        while(end > pos + len - 1)
        {
            _str[end] = _str[end - len];
            end--;
        }
        for(size_t i = 0; i < len; i++)
        {
            _str[pos + i] = str[i];
        }
        _size += len;
    }
    void string::erase(size_t pos, size_t len)
    {
        assert(_size > pos);
        if(len >= _size - pos) // 不能写pos + len , 因为len == npos时为INT_MAX越界
        {
            _size = pos;
            _str[pos] = '\0';
        }
        else
        {
            size_t res = pos + len;
            while(res <= _size)
            {
                _str[pos++] = _str[res++];
            }
            _size -= len;
        }
    }

    size_t string::find(char ch, size_t pos)
    {
        assert(pos < _size);
        for(size_t i = pos; i < _size; i++)
        {
            if(_str[i] == ch)
                return i;
        }
        return npos;
    }

    size_t string::find(const char* str, size_t pos)
    {
        assert(pos < _size);
        const char* res = strstr(_str + pos, str);
        if(res == nullptr)
        {
            return npos;
        }
        return res - _str;
    }

    string string::substr(size_t pos, size_t len)
    {
        assert(pos < _size);
        //len大于字符串长度，更新一下len
        if(len > _size - pos)
        {
            len = _size - pos;
        }

        string sub;
        sub.reserve(len);

        for(size_t i = 0; i < len; i++)
        {
            sub += _str[i + pos];
        }
        return sub;
    }

    bool operator<(const string& s1, const string& s2)
    {
        return strcmp(s1.c_str(), s2.c_str()) < 0;
    }
	bool operator<=(const string& s1, const string& s2)
    {
        return strcmp(s1.c_str(), s2.c_str()) <= 0;

    }
	bool operator>(const string& s1, const string& s2)
    {
        return !(s1 <= s2);
    }
	bool operator>=(const string& s1, const string& s2)
    {
        return !(s1 < s2);

    }
	bool operator==(const string& s1, const string& s2)
    {
        return strcmp(s1.c_str(), s2.c_str()) == 0;

    }
	bool operator!=(const string& s1, const string& s2)
    {
        return !(s1 == s2);

    }

	ostream& operator<<(ostream& out, const string& s)
    {
        for(auto ch : s)
        {
            out << ch;
        }
        return out;
    }

	// istream& operator>>(istream& in, string& s)
    // {
    //     s.clear();
    //     char ch;
    //     ch = in.get();
    //     while(ch != ' ' && ch != '\n')
    //     {
    //         s += ch;
    //         ch = in.get();
    //     }
    //     return in;
    // }
    ////优化istream
    istream& operator>>(istream& in, string& s)
    {
        s.clear();

        const int N = 256;
        char buff[N];
        int i = 0;

        char ch;
        ch = in.get();
        while(ch != ' ' && ch != '\n')
        {
            buff[i++] = ch;
            if(i == N - 1)
            {
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
            ch = in.get();
        }
        if(i > 0)
        {
            buff[i] = '\0';
            s += buff;
        }
        return in;
    }

    istream& getline(istream& in, string& s)
    {
        s.clear();

        const int N = 256;
        char buff[N];
        int i = 0;

        char ch;
        ch = in.get();
        while(ch != '\n')
        {
            buff[i++] = ch;
            if(i == N - 1)
            {
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
            ch = in.get();
        }
        if(i > 0)
        {
            buff[i] = '\0';
            s += buff;
        }
        return in;
    }
}